/*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
_/                                                                            _/
_/                      _/  _/                  _/                            _/
_/       _/_/_/    _/_/_/  _/_/_/      _/_/_/  _/_/_/      _/_/_/  _/  _/_/   _/
_/    _/    _/  _/    _/  _/    _/  _/    _/  _/    _/  _/    _/  _/_/        _/
_/   _/    _/  _/    _/  _/    _/  _/    _/  _/    _/  _/    _/  _/           _/
_/    _/_/_/    _/_/_/  _/_/_/      _/_/_/  _/_/_/      _/_/_/  _/            _/
_/       _/                                                                   _/
_/   _/_/                              Free software copyrighted since 2007   _/
_/                                              <gdbabar@gmail.com>           _/
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#ifdef ENABLE_NLS
#  include <glib/gi18n-lib.h>
#else
#  define _(String) (String)
#endif

#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include <string.h>

#include "common.h"
#include "gdbabar-config.h"

#define LAUNCHER_ICON_SIZE 56
#define COMBO_BOX_PIXBUF_SIZE 18
#define POS_BUTTON_SIZE 16
#define NAME_MAX_LENGTH 40

typedef enum _PosButtonId
{
  POS_BUTTON_FIRST,
  POS_BUTTON_PREVIOUS,
  POS_BUTTON_NEXT,
  POS_BUTTON_LAST
}
PosButtonId;

enum {
  COMBO_BOX_NEW_LAUNCHER,
  COMBO_BOX_SEPARATOR,
  COMBO_BOX_FIRST_LAUNCHER
};

enum {
  COLUMN_TYPE_PIXBUF,
  COLUMN_TYPE_STRING,
  COLUMN_NBR
};

static void create_combo_box_list (GtkComboBox *combo_box, gboolean free);
static void empty_icon_window (void);

static void combo_box_cb (GtkComboBox *widget, gpointer user_data);
static void entry_cb (GtkEditable *editable, gpointer user_data);
static void get_launcher_icon_path_cb (GtkButton *button, gpointer user_data);
static void get_launcher_command_path_cb (GtkButton *button, gpointer user_data);
static void create_new_launcher_cb (GtkButton *button, GtkComboBox *combo_box);
static void delete_launcher_cb (GtkButton *button, GtkComboBox *combo_box);
static void position_button_cb (GtkButton *button, PosButtonId position);

static GtkWidget* position_button_new (gchar *stock_id, GtkBox *box, PosButtonId position);
static GtkWidget* gdbc_bold_label_new (gchar *text, GtkWidget *widget);

/* The returned string should be freed when no longer needed */
static gchar* convert_to_valid_filename (gchar *text);
static gchar* single_desktop_filename_new (gchar *base_name);
static gchar* single_icon_filename_new (gchar *base_name);

static void add_to_order_file (gchar *filename, guint indice);
static void move_after_to_order_file (guint src_indice, guint dest_indice);
static void move_before_to_order_file (guint src_indice, guint dest_indice);
static void remove_to_order_file (guint indice);

static void gtk_multiple_widget_set_sensitive (GtkWidget **widget, gint widget_nbr, gboolean active);
static GdkPixbuf* gdk_pixbuf_new_from_stock_at_size (gchar *stock_id, int width, int height);
static void g_key_file_set_string_to_file (gchar *filename, const gchar *group_name, const gchar *key, const gchar *string);

static gboolean is_combo_box_separator (GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data);
static gboolean is_cache_icon (gchar* filename);

static GtkWidget \
*global_cmd_button,
*global_icon_button,
*global_first_button,
*global_previous_button,
*global_last_button,
*global_next_button,
*global_del_button,
*global_save_button,
*global_name_entry,
*global_cmd_entry,
*global_icon_cpy_check_button,
*global_combo_box;

static gboolean is_new_launcher;

static gchar *icon_path;

GtkWidget*
gdbc_icon_content_new (void)
{

  GtkWidget *v_box, *h_box, *alignment, *table;
  GtkListStore *list_store;
  GtkCellRenderer *cell;

  v_box = gtk_vbox_new (FALSE, 0);

  /* Launcher combo box */
  list_store = gtk_list_store_new (COLUMN_NBR, GDK_TYPE_PIXBUF, G_TYPE_STRING);

  global_combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (list_store));

  create_combo_box_list (GTK_COMBO_BOX (global_combo_box), FALSE);

  cell = gtk_cell_renderer_pixbuf_new ();
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (global_combo_box), cell, FALSE);
  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (global_combo_box), cell, "pixbuf", COLUMN_TYPE_PIXBUF, NULL);

  cell = gtk_cell_renderer_text_new ();
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (global_combo_box), cell, TRUE);
  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (global_combo_box), cell, "text", COLUMN_TYPE_STRING, NULL);

  gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (global_combo_box), is_combo_box_separator, NULL, NULL);
  gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), COMBO_BOX_NEW_LAUNCHER);

  g_signal_connect (G_OBJECT (global_combo_box), "changed", G_CALLBACK(combo_box_cb), NULL);

  gtk_box_pack_start(GTK_BOX (v_box), global_combo_box, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX (v_box), gtk_hseparator_new (), FALSE, FALSE, 4);

  /* Icon chooser */
  global_icon_button = gtk_button_new ();
  g_signal_connect (G_OBJECT (global_icon_button), "clicked", G_CALLBACK(get_launcher_icon_path_cb), NULL);

  table = gtk_table_new (3, 2, FALSE);

  /* Name label and entry */
  global_name_entry = gtk_entry_new ();
  gtk_entry_set_max_length (GTK_ENTRY (global_name_entry), NAME_MAX_LENGTH);
  g_signal_connect (G_OBJECT (global_name_entry), "changed", G_CALLBACK (entry_cb), NULL);

  gtk_table_attach (GTK_TABLE (table),
                    gdbc_bold_label_new (_("_Name :"), global_name_entry),
                    0,
                    1,
                    0,
                    1,
                    GTK_FILL,
                    GTK_FILL,
                    8,
                    0);

  gtk_table_attach (GTK_TABLE (table),
                    global_name_entry,
                    1,
                    2,
                    0,
                    1,
                    GTK_EXPAND | GTK_FILL,
                    GTK_FILL,
                    0,
                    3);

  /* Command label and entry */
  global_cmd_entry = gtk_entry_new ();
  g_signal_connect (G_OBJECT (global_cmd_entry), "changed", G_CALLBACK (entry_cb), NULL);

  gtk_table_attach(GTK_TABLE (table),
                   gdbc_bold_label_new (_("_Command :"), global_cmd_entry),
                   0,
                   1,
                   1,
                   2,
                   GTK_FILL,
                   GTK_FILL,
                   8,
                   0);

  h_box = gtk_hbox_new (FALSE, 8);

  global_cmd_button = gtk_button_new_with_mnemonic (_("_Browse..."));
  g_signal_connect (G_OBJECT (global_cmd_button), "clicked", G_CALLBACK(get_launcher_command_path_cb), NULL);

  gtk_box_pack_start (GTK_BOX (h_box), global_cmd_entry, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (h_box), global_cmd_button, FALSE, FALSE, 0);

  gtk_table_attach (GTK_TABLE (table),
                    h_box,
                    1,
                    2,
                    1,
                    2,
                    GTK_EXPAND | GTK_FILL,
                    GTK_FILL,
                    0,
                    3);

  gtk_table_attach (GTK_TABLE (table),
                    gdbc_bold_label_new (_("Position :"), NULL),
                    0,
                    1,
                    2,
                    3,
                    GTK_FILL,
                    GTK_FILL,
                    8,
                    0);

  alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
  h_box = gtk_hbox_new (FALSE, 4);

  global_first_button = position_button_new (GTK_STOCK_GOTO_FIRST, GTK_BOX (h_box), POS_BUTTON_FIRST);
  global_previous_button = position_button_new (GTK_STOCK_GO_BACK, GTK_BOX (h_box), POS_BUTTON_PREVIOUS);
  global_next_button = position_button_new (GTK_STOCK_GO_FORWARD, GTK_BOX (h_box), POS_BUTTON_NEXT);
  global_last_button = position_button_new (GTK_STOCK_GOTO_LAST, GTK_BOX (h_box), POS_BUTTON_LAST);

  gtk_container_add (GTK_CONTAINER (alignment), h_box);

  gtk_table_attach (GTK_TABLE (table),
                    alignment,
                    1,
                    2,
                    2,
                    3,
                    GTK_EXPAND | GTK_FILL,
                    GTK_FILL,
                    0,
                    3);

  /* Save & Delete button */
  global_save_button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
  g_signal_connect (G_OBJECT (global_save_button), "clicked", G_CALLBACK(create_new_launcher_cb), global_combo_box);

  global_del_button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
  g_signal_connect (G_OBJECT (global_del_button), "clicked", G_CALLBACK(delete_launcher_cb), global_combo_box);

  h_box = gtk_hbox_new (FALSE, 0);

  /* pack icon chooser & table */
  alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);

  gtk_container_add (GTK_CONTAINER (alignment), global_icon_button);
  gtk_box_pack_start (GTK_BOX (h_box), alignment, FALSE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (h_box), table, TRUE, TRUE, 0);

  gtk_box_pack_start (GTK_BOX (v_box), h_box, FALSE, TRUE, 0);

  h_box = gtk_hbox_new (FALSE, 0);

  global_icon_cpy_check_button = gtk_check_button_new_with_label (_("Copy icon in configuration directory (recommanded)"));
  gtk_box_pack_start (GTK_BOX (h_box), global_icon_cpy_check_button, FALSE, FALSE, 2);
  gtk_box_pack_start (GTK_BOX (v_box), h_box, FALSE, FALSE, 4);

  h_box = gtk_hbox_new (FALSE, 0);

  /* pack delete & save button */
  gtk_box_pack_start (GTK_BOX (h_box), global_save_button, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (h_box), global_del_button, FALSE, FALSE, 8);

  gtk_box_pack_start (GTK_BOX (v_box), h_box, FALSE, FALSE, 4);

  empty_icon_window ();

  return v_box;

}

static void
create_combo_box_list (GtkComboBox *combo_box, gboolean free)
{

  GtkTreeModel *tree_model;
  GtkTreeIter iter;
  GdkPixbuf *pixbuf = NULL;
  gchar *ico, *str = NULL;
  gint i;

  tree_model = gtk_combo_box_get_model (combo_box);

  if (free)
    {
      gtk_list_store_clear (GTK_LIST_STORE (tree_model));
    }

  for (i = 0; i < get_launcher_number ()+2; i++)
    {

      if (i == COMBO_BOX_NEW_LAUNCHER)
        {
          str = g_strdup (_("New..."));
          pixbuf = gdk_pixbuf_new_from_stock_at_size (GTK_STOCK_NEW, COMBO_BOX_PIXBUF_SIZE, COMBO_BOX_PIXBUF_SIZE);
        }
      else if (i == COMBO_BOX_SEPARATOR)
        {
          str = NULL;
          pixbuf = NULL;
        }
      else
        {
          str = get_launcher_name_from_index (i-2);
          ico = get_launcher_icon_path_from_index (i-2);
          pixbuf = gdk_pixbuf_new_from_file_at_size (ico, COMBO_BOX_PIXBUF_SIZE, COMBO_BOX_PIXBUF_SIZE, NULL);
          g_free (ico);
        }

      gtk_list_store_append (GTK_LIST_STORE (tree_model), &iter);
      gtk_list_store_set (GTK_LIST_STORE (tree_model), &iter, COLUMN_TYPE_PIXBUF, pixbuf, COLUMN_TYPE_STRING, str, -1);

      if (pixbuf)
        {
          g_object_unref (pixbuf);
        }

      if (str)
        {
          g_free (str);
        }

    }

}

static void
empty_icon_window (void)
{

  GdkPixbuf *pixbuf;

  gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), COMBO_BOX_NEW_LAUNCHER);

  pixbuf = gdk_pixbuf_new_from_file_at_size (DATA_DIR"/system-run.svg", LAUNCHER_ICON_SIZE, LAUNCHER_ICON_SIZE, NULL);
  gtk_button_set_image (GTK_BUTTON (global_icon_button), gtk_image_new_from_pixbuf (pixbuf));
  g_object_unref (pixbuf);

  gtk_entry_set_text (GTK_ENTRY (global_name_entry), "");
  gtk_entry_set_text (GTK_ENTRY (global_cmd_entry), "");

  gtk_multiple_widget_set_sensitive (&global_first_button, 6, FALSE);

  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (global_icon_cpy_check_button), TRUE);

  if (icon_path)
    {
      g_free (icon_path);
    }

  icon_path = NULL;
  is_new_launcher = TRUE;

}

static void
combo_box_cb (GtkComboBox *widget, gpointer user_data)
{

  GdkPixbuf *pixbuf;
  gchar *name, *exec;
  guint index;

  index = gtk_combo_box_get_active (widget);

  if (index == COMBO_BOX_NEW_LAUNCHER)
    {
      empty_icon_window ();
    }
  else
    {

      if (icon_path)
        {
          g_free (icon_path);
        }

      icon_path = get_launcher_icon_path_from_index (index-2);
      pixbuf = gdk_pixbuf_new_from_file_at_size (icon_path, LAUNCHER_ICON_SIZE, LAUNCHER_ICON_SIZE, NULL);
      gtk_button_set_image (GTK_BUTTON (global_icon_button), gtk_image_new_from_pixbuf (pixbuf));
      g_object_unref (pixbuf);

      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (global_icon_cpy_check_button), is_cache_icon (icon_path));

      name = get_launcher_name_from_index (index-2);
      gtk_entry_set_text (GTK_ENTRY (global_name_entry), name);
      g_free (name);

      exec = get_launcher_exec_from_index (index-2);
      gtk_entry_set_text (GTK_ENTRY (global_cmd_entry), exec);
      g_free (exec);

      gtk_widget_set_sensitive (global_del_button, TRUE);

      if (index-2 == 0)
        {
          if (get_launcher_number () > 1)
            {
              gtk_multiple_widget_set_sensitive (&global_last_button, 2, TRUE);
            }
          gtk_multiple_widget_set_sensitive (&global_first_button, 2, FALSE);
        }
      else if (index-1 == get_launcher_number ())
        {
          gtk_multiple_widget_set_sensitive (&global_first_button, 2, TRUE);
          gtk_multiple_widget_set_sensitive (&global_last_button, 2, FALSE);
        }
      else
        {
          gtk_multiple_widget_set_sensitive (&global_first_button, 4, TRUE);
        }

      is_new_launcher = FALSE;
    }

}

static void
entry_cb (GtkEditable *editable, gpointer user_data)
{

  gboolean b;
  gchar *name, *exec, *org_name, *org_exec, *org_icon;
  guint index;

  index = gtk_combo_box_get_active (GTK_COMBO_BOX (global_combo_box));

  name = g_strdup (gtk_entry_get_text (GTK_ENTRY (global_name_entry)));
  exec = g_strdup (gtk_entry_get_text (GTK_ENTRY (global_cmd_entry)));

  if ((is_new_launcher) && (index == 0))
    {
      gtk_widget_set_sensitive (global_save_button, ((strlen (name) > 0) && (strlen(exec) > 0)));
    }
  else if (index >= 2)
    {
      org_name = get_launcher_name_from_index (index-2);
      org_exec = get_launcher_exec_from_index (index-2);
      org_icon = get_launcher_icon_path_from_index (index-2);

      if (icon_path)
        {
          b = (g_ascii_strcasecmp (name, org_name) != 0) ||\
              (g_ascii_strcasecmp (exec, org_exec) != 0) ||\
              (g_ascii_strcasecmp (icon_path, org_icon) != 0);
        }
      else
        {
          b = (g_ascii_strcasecmp (name, org_name) != 0) ||\
              (g_ascii_strcasecmp (exec, org_exec) != 0);
        }

      gtk_widget_set_sensitive (global_save_button, b);

      g_free (org_icon);
      g_free (org_exec);
      g_free (org_name);
    }
  g_free (name);
  g_free (exec);

}

static void
get_launcher_icon_path_cb (GtkButton *button, gpointer user_data)
{

  GtkWidget *chooser;
  GdkPixbuf *pixbuf;
  GtkFileFilter *filter;

  chooser = gtk_file_chooser_dialog_new (_("Get icon file ..."),
                                         GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
                                         GTK_FILE_CHOOSER_ACTION_OPEN,
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                         NULL);

  gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
  gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (chooser), FALSE);

  /* Thanks to Gdmphotosetup authors */
  add_preview_widget (chooser);

  filter = gtk_file_filter_new ();

  gtk_file_filter_add_mime_type (filter, "image/svg+xml");
  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), filter);

  if (gtk_dialog_run (GTK_DIALOG (chooser)) ==  GTK_RESPONSE_ACCEPT)
    {
      if (icon_path)
        {
          g_free (icon_path);
        }
      icon_path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
      pixbuf = gdk_pixbuf_new_from_file_at_size (icon_path, LAUNCHER_ICON_SIZE, LAUNCHER_ICON_SIZE, NULL);
      if (pixbuf)
        {
          gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_pixbuf (pixbuf));
        }
      else
        {
          icon_path = NULL;
        }

      entry_cb (NULL, NULL);
    }

  gtk_widget_destroy (chooser);

}

static void
get_launcher_command_path_cb (GtkButton *button, gpointer user_data)
{

  GtkWidget *chooser;
  GtkFileFilter *filter;
  gchar *text;

  chooser = gtk_file_chooser_dialog_new (_("Get binarie file ..."),
                                         GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
                                         GTK_FILE_CHOOSER_ACTION_OPEN,
                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                         NULL);

  filter = gtk_file_filter_new ();

  gtk_file_filter_add_mime_type (filter, "application/x-executable");
  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), filter);

  if (gtk_dialog_run (GTK_DIALOG (chooser)) ==  GTK_RESPONSE_ACCEPT)
    {
      text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
      gtk_entry_set_text (GTK_ENTRY (global_cmd_entry), text);
      g_free (text);
    }

  gtk_widget_destroy (chooser);

}

static void
create_new_launcher_cb (GtkButton *button, GtkComboBox *combo_box)
{

  GtkWidget *parent;
  gchar *name, *exec, *desktop_file, *icon_file, *base_name;
  guint index;

  parent = gtk_widget_get_toplevel (GTK_WIDGET (button));

  name = g_strdup (gtk_entry_get_text (GTK_ENTRY (global_name_entry)));
  exec = g_strdup (gtk_entry_get_text (GTK_ENTRY (global_cmd_entry)));

  index = gtk_combo_box_get_active (GTK_COMBO_BOX (global_combo_box))-2;

  if (is_new_launcher)
    {
      base_name = convert_to_valid_filename (name);
      desktop_file = single_desktop_filename_new (base_name);
      g_free (base_name);

      create_empty_desktop_entry_file (desktop_file);

      base_name = g_filename_display_basename (desktop_file);
      add_to_order_file (base_name, get_launcher_number ()-1);
      g_free (base_name);
    }
  else
    {
      base_name = get_launcher_file_from_index (index);
      desktop_file = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/", base_name, NULL);
      g_free (base_name);
    }

  if (icon_path)
    {
      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (global_icon_cpy_check_button)))
        {
          if (is_new_launcher)
            {
              base_name = convert_to_valid_filename (name);
              icon_file = single_icon_filename_new (base_name);
              g_free (base_name);
            }
          else
            {
              icon_file = get_launcher_icon_path_from_index (index);
              if (!is_cache_icon (icon_file))
                {
                  g_free (icon_file);
                  base_name = convert_to_valid_filename (name);
                  icon_file = single_icon_filename_new (base_name);
                  g_free (base_name);
                }
            }
          g_file_copy (icon_path, icon_file);
          g_free (icon_path);
          icon_path = icon_file;
        }
    }
  else
    {
      icon_path = g_strdup (DATA_DIR"/system-run.svg");
    }

  g_key_file_set_string_to_file (desktop_file, "Desktop Entry", "Name", name);
  g_key_file_set_string_to_file (desktop_file, "Desktop Entry", "Exec", exec);
  g_key_file_set_string_to_file (desktop_file, "Desktop Entry", "Icon", icon_path);

  g_free (desktop_file);

  if ((icon_path) && (is_new_launcher))
    {
      g_free (icon_path);
      icon_path = NULL;
    }

  common_infobox (GTK_WINDOW (parent), _("Successfully created"));

  create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);

  if (is_new_launcher)
    {
      index = get_launcher_number ()-1;
    }

  gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), index+2);

  gtk_multiple_widget_set_sensitive (&global_first_button, 2, FALSE);
  gtk_widget_set_sensitive (global_save_button, FALSE);
  is_new_launcher = FALSE;
  combo_box_cb (GTK_COMBO_BOX (global_combo_box), NULL);

  g_free (exec);
  g_free (name);

}

static void
delete_launcher_cb (GtkButton *button, GtkComboBox *combo_box)
{

  gchar *basename, *filename, *ico_path;
  guint index;

  index = gtk_combo_box_get_active (GTK_COMBO_BOX (global_combo_box))-2;

  ico_path = get_launcher_icon_path_from_index (index);

  if (is_cache_icon (ico_path))
    {
      g_remove (ico_path);
    }
  g_free (ico_path);

  basename = get_launcher_file_from_index (index);
  filename = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/", basename, NULL);

  g_remove (filename);

  g_free (basename);
  g_free (filename);

  remove_to_order_file (index);

  create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);
  empty_icon_window ();

}

static void
position_button_cb (GtkButton *button, PosButtonId position)
{

  guint index;

  index = gtk_combo_box_get_active (GTK_COMBO_BOX (global_combo_box))-2;

  switch (position)
    {
    case POS_BUTTON_FIRST:
      move_before_to_order_file (index, 0);
      create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);
      gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), 2);
      break;
    case POS_BUTTON_NEXT:
      move_after_to_order_file (index, index+1);
      create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);
      gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), index+3);
      break;
    case POS_BUTTON_PREVIOUS:
      move_before_to_order_file (index, index-1);
      create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);
      gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), index+1);
      break;
    case POS_BUTTON_LAST:
      move_after_to_order_file (index, get_launcher_number ()-1);
      create_combo_box_list (GTK_COMBO_BOX (global_combo_box), TRUE);
      gtk_combo_box_set_active (GTK_COMBO_BOX (global_combo_box), get_launcher_number ()+1);
      break;
    }

}

static GtkWidget*
position_button_new (gchar *stock_id, GtkBox *box, PosButtonId position)
{

  GtkWidget *button;
  GdkPixbuf *pixbuf;

  button = gtk_button_new ();
  pixbuf = gdk_pixbuf_new_from_stock_at_size (stock_id, POS_BUTTON_SIZE, POS_BUTTON_SIZE);

  gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_pixbuf (pixbuf));

  gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);

  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK(position_button_cb), (gpointer)position);

  g_object_unref (pixbuf);

  return button;

}

static GtkWidget*
gdbc_bold_label_new (gchar *text, GtkWidget *widget)
{

  GtkWidget *label;
  gchar *str;

  str = g_strdup_printf ("<b>%s</b>", text);
  label = gtk_label_new (NULL);

  if (widget)
    {
      gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str);
      gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
    }
  else
    {
      gtk_label_set_markup (GTK_LABEL (label), str);
    }

  g_free (str);

  gtk_misc_set_alignment (GTK_MISC(label), 1.0, 0.5);

  return label;

}

static gchar*
convert_to_valid_filename (gchar *text)
{

  gchar buffer[NAME_MAX_LENGTH+10];
  gunichar c;
  gint i, j = 0;

  memset (buffer, 0, sizeof buffer);

  for (i = 0; i < strlen (text); i++)
    {
      c = g_unichar_tolower (text[i]);

      if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-')
        {
          buffer[j] = c;
          j++;
        }
      else if (c == '.' || c == ' ')
        {
          buffer[j] = '-';
          j++;
        }
    }

  return g_strdup (buffer);

}

static gchar*
single_desktop_filename_new (gchar* base_name)
{

  gchar *desktop_file, *path;
  guint i;

  path = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/", NULL);

  desktop_file =  g_strconcat (path, base_name, ".desktop", NULL);

  for (i = 0; g_file_test (desktop_file, G_FILE_TEST_EXISTS); i++)
    {
      g_free (desktop_file);
      desktop_file = g_strdup_printf ("%s%s_%u.desktop", path, base_name, i);
    }

  g_free (path);

  return desktop_file;

}

static gchar*
single_icon_filename_new (gchar* base_name)
{

  gchar *ico_path, *path;
  guint i;

  path = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/icons/", NULL);

  ico_path = g_strconcat (path, base_name, ".svg", NULL);

  for (i = 0; g_file_test (ico_path, G_FILE_TEST_EXISTS); i++)
    {
      g_free (ico_path);
      ico_path = g_strdup_printf ("%s%s_%u.svg", path, base_name, i);
    }

  g_free (path);

  return ico_path;

}

static void
add_to_order_file (gchar *filename, guint indice)
{

  gchar *order_file, *key;

  order_file = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/.order", NULL);
  key = g_strdup_printf ("%u", indice);

  g_key_file_set_string_to_file (order_file, "Order", key, filename);

  g_free (key);
  g_free (order_file);

}

static void
move_after_to_order_file (guint src_indice, guint dest_indice)
{

  GKeyFile *key_file;
  gchar *order_file, *basename, *data, *key = NULL;
  guint i, j = 0;

  key_file = g_key_file_new ();

  for (i = 0; i < get_launcher_number (); i++)
    {

      if (i == dest_indice)
        {
          basename = get_launcher_file_from_index (dest_indice);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;

          basename = get_launcher_file_from_index (src_indice);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;
        }
      else if (i != src_indice)
        {
          basename = get_launcher_file_from_index (i);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;
        }

    }

  data = g_key_file_to_data (key_file, NULL, NULL);

  order_file = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/.order", NULL);
  g_file_set_contents (order_file, data, -1, NULL);

  g_free (data);
  g_free (order_file);

  g_key_file_free (key_file);

}

static void
move_before_to_order_file (guint src_indice, guint dest_indice)
{

  GKeyFile *key_file;
  gchar *order_file, *basename, *data, *key = NULL;
  guint i, j = 0;

  key_file = g_key_file_new ();

  for (i = 0; i < get_launcher_number (); i++)
    {

      if (i == dest_indice)
        {
          basename = get_launcher_file_from_index (src_indice);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;

          basename = get_launcher_file_from_index (dest_indice);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;
        }
      else if (i != src_indice)
        {
          basename = get_launcher_file_from_index (i);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;
        }

    }

  data = g_key_file_to_data (key_file, NULL, NULL);

  order_file = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/.order", NULL);
  g_file_set_contents (order_file, data, -1, NULL);

  g_free (data);
  g_free (order_file);

  g_key_file_free (key_file);

}

static void
remove_to_order_file (guint indice)
{

  GKeyFile *key_file;
  gchar *order_file, *basename, *data, *key = NULL;
  guint i, j = 0;

  key_file = g_key_file_new ();

  for (i = 0; i < get_launcher_number ()+1; i++)
    {
      if (i != indice)
        {
          basename = get_launcher_file_from_index (i);
          key = g_strdup_printf ("%u", j);
          g_key_file_set_string (key_file, "Order", key, basename);
          g_free (key);
          g_free (basename);
          ++j;
        }
    }

  if (j > 0)
    {
      data = g_key_file_to_data (key_file, NULL, NULL);
    }
  else
    {
      data = g_strdup ("[Order]");
    }

  order_file = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/desktop/.order", NULL);
  g_file_set_contents (order_file, data, -1, NULL);

  g_free (data);
  g_free (order_file);

  g_key_file_free (key_file);

}

static void
gtk_multiple_widget_set_sensitive (GtkWidget **widget, gint widget_nbr, gboolean active)
{

  gint i;

  for (i = 0; i < widget_nbr; i++)
    {
      gtk_widget_set_sensitive (*widget, active);
      widget++;
    }

}

static GdkPixbuf*
gdk_pixbuf_new_from_stock_at_size(gchar *stock_id, int width, int height)
{

  GtkWidget *image;
  GdkPixbuf *pixbuf, *resize_pixbuf;

  image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
  pixbuf = gtk_widget_render_icon (image, stock_id, GTK_ICON_SIZE_BUTTON, NULL);
  resize_pixbuf = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);

  gtk_widget_destroy (image);
  g_object_unref (pixbuf);

  return resize_pixbuf;

}

static void
g_key_file_set_string_to_file (gchar *filename, const gchar *group_name, const gchar *key, const gchar *string)
{

  GKeyFile *key_file;
  GMappedFile *file;
  gchar *contents, *data;

  file = g_mapped_file_new (filename, FALSE, NULL);
  contents = g_mapped_file_get_contents (file);

  key_file = g_key_file_new ();

  g_key_file_load_from_data (key_file, contents, g_mapped_file_get_length (file), G_KEY_FILE_NONE, NULL);
  g_key_file_set_string (key_file, group_name, key, string);

  data = g_key_file_to_data (key_file, NULL, NULL);

  g_key_file_free (key_file);

  g_mapped_file_free (file);

  g_file_set_contents (filename, data, -1, NULL);
  g_free (data);

}

static gboolean
is_combo_box_separator (GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
{

  GtkTreePath *path;
  gint i;

  path = gtk_tree_model_get_path (tree_model, iter);
  i = gtk_tree_path_get_indices (path)[0];
  gtk_tree_path_free (path);

  return (i == COMBO_BOX_SEPARATOR);

}

static gboolean
is_cache_icon (gchar* filename)
{

  gchar *path, *dirname;
  gboolean b;

  path = g_strconcat (g_get_home_dir (), HOME_CONF_DIR"/icons", NULL);

  dirname = g_path_get_dirname (filename);

  b = (g_ascii_strcasecmp (path, dirname) == 0);

  g_free (dirname);
  g_free (path);

  return b;

}

